import wx
import math 
from log_object import *

def makeNew(parent, window, param1):
    """ this is how we instantiate the device object from
        the main program that loads this plugin """
    return TrendGraph(parent, window, param1)

class TrendGraph:
	def __init__(self, parent, window, param1):
		self.parent = parent
		self.window = window

		self.type = TRENDGRAPH
		self.param1 = param1
		self.param2 = NOT_DEFINED 

		self.log_date = ""
		self.start = 0
		self.end = 0 
		self.panel_end = 0 
		self.dim = [] 
		self.space = [] 

	def draw(self, dc, start, end, dim, space):
                dc.SetBackground(wx.Brush(wx.Colour(255,255,255)))
                dc.Clear()

		self.start = start
		self.end = end 
		self.panel_end =  end 
		self.dim = dim
		self.space = space

		dc.SetBrush(wx.TRANSPARENT_BRUSH)
		dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1))
		dc.SetTextBackground(wx.Colour(0,0,0))
		dc.SetTextForeground(wx.Colour(0,0,0))
		font = wx.Font(15, wx.TELETYPE, wx.NORMAL, wx.BOLD)
		dc.SetFont(font)

		window_width = int(self.window.Width / space[0])
		window_height = int(self.window.Height / space[1])

		# 1. draw vertical line & information
		x = (dim[0] * window_width) + 30
		origin_x = x
		y = (dim[1] * window_height) + window_height -61
		dc.DrawLines(((x, dim[1] * window_height), (x, y)))
		right_gap = 50
		graph_width = window_width - right_gap 
		endx = (dim[0] * window_width) + graph_width 
		dc.DrawText("cases", window_width - 70, y+10)

 		y_start = dim[1] * window_height 
		dc.DrawLines(((x-5, y), (endx+right_gap, y)))

		max = len(self.parent.log_list)
		each_case = (graph_width * 1.0) / max 
		dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1, style=wx.DOT))
		font = wx.Font(12, wx.TELETYPE, wx.NORMAL, wx.BOLD)
		dc.SetFont(font)
		dc.DrawText("1", origin_x-7, y+10)
		x1 = origin_x  + each_case 
		y1 = dim[1] * window_height
		max += 1
		for i in range(2, max):
			dc.DrawLines(((x1, y1), (x1, y)))
			dc.DrawText(str(i), x1-7, y+10)
			x1 += each_case

		if self.param1 == LOG_POINTER_VECTOR :
			self._drawVector(dc, window_width, window_height, x, y, origin_x, endx, each_case)
		elif self.param1 == LOG_POINTER_ACTIVE :
			self._drawActive(dc, window_width, window_height, x, y, origin_x, endx, each_case)
		elif self.param1 == LOG_POINTER_CLICK :
			self._drawClick(dc, window_width, window_height, x, y, origin_x, endx, each_case)
		#elif self.param1 == LOG_WINDOW_NEW :
		#	self._drawWindow(dc, window_width, window_height, x, y, origin_x, endx, each_case)



	def _get2PointList(self, user,  trend_list): 
		l = []
		for trend in trend_list : 
			for T in trend : 
				if T[0] == user : 
					temp = (T[1], T[2])
					l.append(temp)
		return l


	def _get3PointList(self, user,  trend_list): 
		l = []
		for trend in trend_list : 
			for T in trend : 
				if T[0] == user : 
					temp = (T[1], T[2], T[3])
					l.append(temp)
		return l


	def _verify(self, trend_list, current_list, no_param): 
		if len(trend_list) > 0 : 
			for L in current_list: 
				name = L[0] 
				flag = False
				for T_list in trend_list: 
					for T in T_list: 
						if name == T[0]: 
							flag = True
							break
				if flag == False : 
					if no_param == 2 :
						temp = (name, -1, -1)
					else :
						temp = (name, -1, -1, -1)
					for T_list in trend_list: 
						T_list.append(temp)


		for T_list in trend_list: 
			for T in T_list: 
				name = T[0] 
				flag = False
				for L in current_list: 
					if name == L[0]: 
						flag = True
						break
				if flag == False : 
					if no_param == 2 :
						temp = (name, -1, -1)
					else :
						temp = (name, -1, -1, -1)
					current_list.append(temp)


	def _drawVector(self, dc, window_width, window_height, x, y, origin_x, endx, each_case):
		right_gap = 50
		each_height = int((window_height -61 - 10.0) / 2)

		dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1))
		dc.DrawLines(((x-30, y - each_height -5), (endx+right_gap, y- each_height - 5)))

		#if self.param1 == LOG_POINTER_MOVE :
		trend_list = []
		user_list = []
		max_1 =0
		max_2 =0
		min_1 = 999
		min_2 = 999
		for current_log in self.parent.log_list :
			l = [] 
			for pointer in current_log.pointer_list: 
				if not (pointer.name in user_list) : 
					user_list.append(pointer.name)

				prev_x = -1
				prev_y = -1
				dir_x = 0
				dir_y = 0
				count = 0
				for log in pointer.log_list: 
					if log.mode == LOG_POINTER_MOVE or log.mode == LOG_POINTER_CLICK or log.mode == LOG_POINTER_RELEASE:
						if prev_x != -1:
							dx = log.x - prev_x
							dy = log.y - prev_y
							unit_length = math.sqrt(dx * dx +  dy * dy)
							if unit_length > 0 : 
        							unitDx = dx / unit_length;
								unitDy = dy / unit_length;
								unitX1 = prev_x + unitDx
								unitY1 = prev_y + unitDy

								if math.fabs(unitDx) > math.fabs(unitDy) :  
									dir_x += 1
								else :
									dir_y += 1
								count += 1

						prev_x = log.x 
						prev_y = log.y 
 					elif log.mode == LOG_POINTER_REMOVE or log.mode == LOG_POINTER_NEW :
						prev_x = -1
						prev_y = -1

				dir_x = int((dir_x * 1.0 / count) * 100)
				dir_y = int((dir_y * 1.0 / count) * 100)
				if dir_x > max_1 :
					max_1 = dir_x
				if dir_x < min_1 :
					min_1 = dir_x
				if dir_y > max_2 :
					max_2 = dir_y
				if dir_y < min_2 :
					min_2 = dir_y

				temp = (pointer.name, dir_x, dir_y)
				l.append(temp)
			# verification...
			self._verify(trend_list, l, 2)
			trend_list.append(l)

		dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1, style=wx.DOT))
		y1 = int(each_height / 2.0)
		y_start = self.dim[1] * window_height
		dc.DrawLines(((x-5, y1), (endx+right_gap, y1)))
		dc.DrawText("pointer's vector: x-oriented (%)", x+10, y_start + 10)
		y1 += each_height + 10
		dc.DrawLines(((x-5, y1), (endx+right_gap, y1)))
		dc.DrawText("pointer's vector: y-oriented (%)", x+10, y_start + each_height + 20)

		dis_1  = max_1 - min_1
		dis_2  = max_2 - min_2
		if dis_1 > dis_2 : 
			dis_2 = dis_1
		if dis_2 <= 30 : 
			dis_2 = 30
		y_unit = 1.0 * each_height/ dis_2

		y1 =  each_height
		dc.DrawText(str(min_1), x-20, y1-5)
		y1 =  each_height - int(y_unit * (max_1-min_1))
		dc.DrawText(str(max_1), x-20, y1-5)
		y1 =  each_height - int(y_unit * dis_2)
		if (min_1 + dis_2) != max_1 : 
			dc.DrawText(str(min_1+ dis_2), x-20, y1-5)

		y1 =  window_height -61
		dc.DrawText(str(min_2), x-20, y1-5)
		y1 =  window_height -61 - int(y_unit * (max_2-min_2))
		dc.DrawText(str(max_2), x-20, y1-5)
		y1 =  window_height -61 - int(y_unit * dis_2)
		if (min_2 + dis_2) != max_2 : 
			dc.DrawText(str(min_2+ dis_2), x-20, y1-5)

		x = window_width - 60

		idx = 0
		for user in user_list : 
			if self.parent.isSelectedUser(user) == False:
				continue
			color = self.parent.getColor(idx+2)
			dc.SetPen(wx.Pen(color, 2))
			dc.SetBrush(wx.Brush(color))

			x1 = origin_x 
			point_list = self._get2PointList(user, trend_list)
			prev_x = -1
			prev_y1 = -1
			prev_y2 = -1
			for l in point_list :
				if l[0] == -1: 
					y1 = prev_y1
				else:
					y1 =  each_height - int(y_unit * (l[0]-min_1))
				#dc.DrawCircle(x1, y1, 5)
				dc.DrawText(str(l[0]), x1-5, y1+10)
				
				if prev_x != -1 : 
					dc.DrawLines(((prev_x, prev_y1), (x1, y1)))
				prev_y1 = y1 
				
				if l[1] == -1: 
					y1 = prev_y2
				else:
					y1 =  window_height -61 - int(y_unit * (l[1]-min_2))

				#dc.DrawCircle(x1, y1, 5)
				dc.DrawText(str(l[1]), x1-5, y1+10)

				if prev_x != -1 : 
					dc.DrawLines(((prev_x, prev_y2), (x1, y1)))

				prev_x = x1 
				prev_y2 = y1 

				x1 += each_case
			del point_list 

			y1 = (idx * 15) + 30
			dc.DrawRectangle(x, y1, 60, 15)
			dc.DrawText(user, x, y1)
			idx  += 1


		for trend in trend_list : 
			for l in trend : 
				del l
			del trend
		del trend_list 
		for user in user_list : 
			del user
		del user_list


	def _drawActive(self, dc, window_width, window_height, x, y, origin_x, endx, each_case):
		right_gap = 50
		each_height = int((window_height -61 - 15.0) / 3)

		dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1))
		dc.DrawLines(((x-30, y - each_height -5), (endx+right_gap, y- each_height - 5)))
		dc.DrawLines(((x-30, y - (each_height +5)*2), (endx+right_gap, y- (each_height+5)*2)))

		trend_list = []
		user_list = []
		max_1 =0
		max_2 =0
		max_3 =0
		min_1 = 999
		min_2 = 999
		min_3 = 999
		for current_log in self.parent.log_list :
			end = current_log.duration
			l = [] 
			for pointer in current_log.pointer_list: 
				if not (pointer.name in user_list) : 
					user_list.append(pointer.name)

				active_period = 0
				inactive_period = 0
				for active_slot in pointer.active_range:
					active_start = active_slot[1] / 60
					active_end = active_slot[2] / 60

					# setting color for status
					if active_slot[0] == 0 :
						active_period += (active_end - active_start) 
						inactive_period += (active_end - active_start) 
					else :
						active_period += (active_end - active_start) 

				active_period = int((active_period * 1.0 / end) * 100)
				inactive_period = int((inactive_period * 1.0 / end) * 100)
				inactive_portion = int((inactive_period * 1.0 / active_period) * 100)
				if active_period > max_1 :
					max_1 =  active_period
				if active_period < min_1 :
					min_1 = active_period
				if inactive_period > max_2 :
					max_2 = inactive_period
				if inactive_period < min_2 :
					min_2 = inactive_period 
				if inactive_portion > max_3 :
					max_3 = inactive_portion
				if inactive_portion < min_3 :
					min_3 = inactive_portion
				temp = (pointer.name, active_period, inactive_period, inactive_portion)
				l.append(temp)
			self._verify(trend_list, l, 3)
			trend_list.append(l)

		dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1, style=wx.DOT))
		y_start = self.dim[1] * window_height
		y1 = y_start + int(each_height / 2.0)
		dc.DrawLines(((x-5, y1), (endx+right_gap, y1)))
		dc.DrawText("pointer on screen (%)", x+10, y_start + 10)
		y1 += each_height +5 
		dc.DrawLines(((x-5, y1), (endx+right_gap, y1)))
		dc.DrawText("pointer on screen, but inactive (%)", x+10, y_start + each_height + 15)
		y1 += each_height +5 
		dc.DrawLines(((x-5, y1), (endx+right_gap, y1)))
		dc.DrawText("inactive/pointer on screen = (%)", x+10, y_start + each_height * 2 + 20)

		dis_1 = max_1 - min_1
		dis_2 = max_2 - min_2
		dis_3 = max_3 - min_3
		if dis_1 > dis_3 : 
			dis_3 = dis_1
		if dis_2 > dis_3 : 
			dis_3 = dis_2
		if dis_3 < 30 :
			dis_3 = 30

		y_unit = 1.0 * each_height/ dis_3 

		y1 =  each_height
		dc.DrawText(str(min_1), x-20, y1-5)
		y1 =  each_height - int(y_unit * (max_1-min_1))
		dc.DrawText(str(max_1), x-20, y1-5)
		y1 =  each_height - int(y_unit * dis_3)
		if (min_1 + dis_3) != max_1 : 
			dc.DrawText(str(min_1+ dis_3), x-20, y1)

		y1 =  each_height *2
		dc.DrawText(str(min_2), x-20, y1)
		y1 =  each_height *2 - int(y_unit * (max_2-min_2))
		dc.DrawText(str(max_2), x-20, y1)
		y1 =  each_height *2  - int(y_unit * dis_3)
		if (min_2 + dis_3) != max_2 : 
			dc.DrawText(str(min_2+ dis_3), x-20, y1+5)

		y1 =  window_height -61
		dc.DrawText(str(min_3), x-20, y1)
		y1 =  window_height -61 - int(y_unit * (max_3-min_3))
		dc.DrawText(str(max_3), x-20, y1)
		y1 =  window_height -61 - int(y_unit * dis_3)
		if (min_3 + dis_3) != max_3 : 
			dc.DrawText(str(min_3+ dis_3), x-20, y1-5)
		x = window_width - 60

		# average...
		'''
		m1 = 0
		m2 = 0
		for user in user_list : 
			if self.parent.isSelectedUser(user) == False:
				continue
			point_list = self._get3PointList(user, trend_list)
			for l in point_list :
				print l
				m1 += l[0]
				m2 += l[2]
		user_count = 1.0 * len(user_list)
		m1 /= (user_count * 4)
		m2 /= (user_count * 4)
		print m1, m2
		'''


		idx = 0
		for user in user_list : 
			if self.parent.isSelectedUser(user) == False:
				continue
			color = self.parent.getColor(idx+2)
			dc.SetPen(wx.Pen(color, 2))
			dc.SetBrush(wx.Brush(color))

			x1 = origin_x 
			point_list = self._get3PointList(user, trend_list)
			prev_x = -1
			prev_y1 = -1
			prev_y2 = -1
			prev_y3 = -1
			for l in point_list :
				if l[0] == -1 :
					y1 = prev_y1
				else :
					y1 =  each_height - int(y_unit * (l[0] -min_1))
				#dc.DrawCircle(x1, y1, 5)
				dc.DrawText(str(l[0]), x1-5, y1+10)
				
				if prev_x != -1 : 
					dc.DrawLines(((prev_x, prev_y1), (x1, y1)))
				prev_y1 = y1 
				
				#y1 =  window_height -61 - int(each_height * 1.0 * l[1] / 100)
				if l[1] == -1 :
					y1 = prev_y2
				else :
					y1 =  each_height *2  - int(y_unit * (l[1] -min_2))

				#dc.DrawCircle(x1, y1, 5)
				dc.DrawText(str(l[1]), x1-5, y1+10)

				if prev_x != -1 : 
					dc.DrawLines(((prev_x, prev_y2), (x1, y1)))
				prev_y2 = y1 
				
				if l[2] == -1 :
					y1 = prev_y3
				else :
					y1 =  window_height -61 - int(y_unit * (l[2] -min_3))
				#dc.DrawCircle(x1, y1, 5)
				dc.DrawText(str(l[2]), x1-5, y1+10)

				if prev_x != -1 : 
					dc.DrawLines(((prev_x, prev_y3), (x1, y1)))

				prev_x = x1 
				prev_y3 = y1 

				x1 += each_case
			del point_list 

			y1 = (idx * 15) + 30
			dc.DrawRectangle(x, y1, 60, 15)
			dc.DrawText(user, x, y1)
			idx  += 1


		for trend in trend_list : 
			for l in trend : 
				del l
			del trend
		del trend_list 
		for user in user_list : 
			del user
		del user_list


	def _drawClick(self, dc, window_width, window_height, x, y, origin_x, endx, each_case):
		right_gap = 50
		each_height = int((window_height -61 - 15.0) / 3)

		dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1))
		dc.DrawLines(((x-30, y - each_height -5), (endx+right_gap, y- each_height - 5)))
		dc.DrawLines(((x-30, y - (each_height +5)*2), (endx+right_gap, y- (each_height+5)*2)))

		trend_list = []
		user_list = []
		max_1 =0
		max_2 =0
		max_3 =0
		min_1 = 999
		min_2 = 999
		min_3 = 999
		for current_log in self.parent.log_list :
			end = current_log.duration
			l = [] 
			for pointer in current_log.pointer_list: 
				if not (pointer.name in user_list) : 
					user_list.append(pointer.name)

				no1 = int(pointer.no_clicks * 60 / end)
				no2 = int(pointer.no_dclicks * 60 / end)
				no3 = int(pointer.no_drags * 60 / end)

				if no1 > max_1 :
					max_1 = no1
				if no2 > max_2 :
					max_2 = no2
				if no3 > max_3 :
					max_3 = no3

				if no1 > max_1 :
					max_1 = no1
				if no1 < min_1 :
					min_1 = no1
				if no2 > max_2 :
					max_2 = no2
				if no2 < min_2 :
					min_2 = no2
				if no3 > max_3 :
					max_3 = no3
				if no3 < min_3 :
					min_3 = no3

				temp = (pointer.name, no1, no2, no3)
				l.append(temp)
			self._verify(trend_list, l, 3)
			trend_list.append(l)

		dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1, style=wx.DOT))
		y_start = self.dim[1] * window_height
		y1 = y_start + int(each_height / 2.0)
		dc.DrawLines(((x-5, y1), (endx+right_gap, y1)))
		dc.DrawText("no of click /hr (max =" + str(max_1) + ")", x+10, y_start + 10)
		y1 += each_height +5 
		dc.DrawLines(((x-5, y1), (endx+right_gap, y1)))
		dc.DrawText("no of double click /hr (max =" + str(max_2) + ")", x+10, y_start + each_height + 15)
		y1 += each_height +5 
		dc.DrawLines(((x-5, y1), (endx+right_gap, y1)))
		dc.DrawText("no of drag /hr (max =" +str(max_3) + ")", x+10, y_start + each_height * 2 + 20)

		dis_1 = max_1 - min_1
		dis_2 = max_2 - min_2
		dis_3 = max_3 - min_3
		if dis_1 > dis_3 : 
			dis_3 = dis_1
		if dis_2 > dis_3 : 
			dis_3 = dis_2
		if dis_3 < 30 :
			dis_3 = 30

		y_unit = 1.0 * each_height/ dis_3 

		y1 =  each_height
		dc.DrawText(str(min_1), x-20, y1-5)
		y1 =  each_height - int(y_unit * (max_1-min_1))
		dc.DrawText(str(max_1), x-20, y1-5)
		y1 =  each_height - int(y_unit * dis_3)
		if (min_1 + dis_3) != max_1 : 
			dc.DrawText(str(min_1+ dis_3), x-20, y1)

		y1 =  each_height *2
		dc.DrawText(str(min_2), x-20, y1)
		y1 =  each_height *2 - int(y_unit * (max_2-min_2))
		dc.DrawText(str(max_2), x-20, y1)
		y1 =  each_height *2  - int(y_unit * dis_3)
		if (min_2 + dis_3) != max_2 : 
			dc.DrawText(str(min_2+ dis_3), x-20, y1+5)

		y1 =  window_height -61
		dc.DrawText(str(min_3), x-20, y1)
		y1 =  window_height -61 - int(y_unit * (max_3-min_3))
		dc.DrawText(str(max_3), x-20, y1)
		y1 =  window_height -61 - int(y_unit * dis_3)
		if (min_3 + dis_3) != max_3 : 
			dc.DrawText(str(min_3+ dis_3), x-20, y1-5)
		x = window_width - 60

		idx = 0
		if max_1 == 0 :
			max_1 =1
		if max_2 == 0 :
			max_2 =1
		if max_3 == 0 :
			max_3 =1
		for user in user_list : 
			if self.parent.isSelectedUser(user) == False:
				continue
			color = self.parent.getColor(idx+2)
			dc.SetPen(wx.Pen(color, 2))
			dc.SetBrush(wx.Brush(color))

			x1 = origin_x 
			point_list = self._get3PointList(user, trend_list)
			prev_x = -1
			prev_y1 = -1
			prev_y2 = -1
			prev_y3 = -1
			for l in point_list :
				if l[0] == -1 : 
					y1 =  each_height +5 - int(y_unit * - min_1)
				else :
					y1 =  each_height +5 - int(y_unit * (l[0] - min_1))
				#dc.DrawCircle(x1, y1, 5)
				dc.DrawText(str(l[0]), x1-5, y1+10)
				
				if prev_x != -1 : 
					dc.DrawLines(((prev_x, prev_y1), (x1, y1)))
				prev_y1 = y1 
				
				#y1 =  window_height -61 - int(each_height * 1.0 * l[1] / max_2)
				if l[1] == -1 : 
					y1 =  each_height *2 +10  - int(y_unit * -min_2)
				else :
					y1 =  each_height *2 +10  - int(y_unit * (l[1]  -min_2))
				#dc.DrawCircle(x1, y1, 5)
				dc.DrawText(str(l[1]), x1-5, y1+10)

				if prev_x != -1 : 
					dc.DrawLines(((prev_x, prev_y2), (x1, y1)))
				prev_y2 = y1 
				
				if l[2] == -1 : 
					y1 =  window_height -61 - int(y_unit * -min_3)
				else :
					y1 =  window_height -61 - int(y_unit * (l[2] -min_3))
				#dc.DrawCircle(x1, y1, 5)
				dc.DrawText(str(l[2]), x1-5, y1+10)

				if prev_x != -1 : 
					dc.DrawLines(((prev_x, prev_y3), (x1, y1)))

				prev_x = x1 
				prev_y3 = y1 

				x1 += each_case
			del point_list 

			y1 = (idx * 15) + 30
			dc.DrawRectangle(x, y1, 60, 15)
			dc.DrawText(user, x, y1)
			idx  += 1


		for trend in trend_list : 
			for l in trend : 
				del l
			del trend
		del trend_list 
		for user in user_list : 
			del user
		del user_list


